package effectiveJava.reflect.proxy;

import sun.misc.ProxyGenerator;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Created by dycong on 2017/9/17.
 */
public class DynamicProxy2 implements InvocationHandler {
    private Subject subject = null;

    public DynamicProxy2(Subject _subject) {
        subject = _subject;
    }

    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        before();
        Object o;
        if ("request".equals(method.getName())) {
            o = subject.request();
        } else {
            o = subject.response();
        }
        after();
        return o;
    }

    private void before() {
        System.out.println(0);
    }

    private void after() {
        System.out.println(1);
    }

    /*动态代理场景类*/
    public static void main(String[] args) {
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
        Subject subject = new RealSubject();
        DynamicProxy2 dynamicProxy = new DynamicProxy2(subject);

        //当前加载器
        ClassLoader loader = subject.getClass().getClassLoader();
        //动态代理,可参考 demo/demo3的JDK代理实现
        Subject proxy = (Subject) Proxy.newProxyInstance(loader, subject.getClass().getInterfaces(), dynamicProxy);
        System.out.println(proxy.request());
        System.out.println(proxy.response());
        createProxyClassFile();
    }

    private static void createProxyClassFile(){
        String name = "ProxySubject";
        byte[] data = ProxyGenerator.generateProxyClass(name,new Class[]{Subject.class});
        FileOutputStream out =null;
        try {
            out = new FileOutputStream(name+".class");
            System.out.println((new File("hello")).getAbsolutePath());
            out.write(data);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(null!=out) try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /*
    todo 1. 抽象主题角色，2. 具体主题角色, 3. InvocationHandler
    todo InvocationHandler，动态代理是根据被代理的接口实现所有方法的，也就说给他一个或多个接口，动态代理会宣称“我已经实现接口下 的所有方法了”，
    todo 在默认情况下，自动生成的这些方法返回值都是为空的，代理虽然实现了它，但是没有赋予任何的逻辑意义，最后所有的逻辑方法都是通过
    todo InvocationHandler实现的，由Handler处理：
    todo public Object invoke(Object proxy, Method method, Object[] args)
    todo  proxy：动态生成的代理，method：通过代理调用的方法， args：参数
    todo 通过：Object result = method.invoke(target, args); //target为传入的具体主题角色真正执行逻辑
     */
}
